<template>
  <div class="box" ref="boxRef">
    <div class="flex">
      <div class="title">
        服务组
        <el-tooltip
          effect="dark"
          :show-after="500"
          content="至多5级，所有服务组支持设置负责人，仅末级服务组支持设置成员"
          placement="top-start"
        >
          <i class="MC_iconfont MC_icon-xinxi-line"></i>
        </el-tooltip>
      </div>
      <div class="icon-list">
        <i @click="init" class="MC_iconfont MC_icon-shuaxin"></i>
      </div>
    </div>
    <el-input
      class="tree-search"
      placeholder="输入组织名称"
      :prefix-icon="Search"
      v-model.trim="query"
      @input="onChange"
    />
    <div class="tree-box">
      <el-tree-v2
        @scroll="onHideMenu"
        @node-click="onNodeClick"
        class="tree"
        :expand-on-click-node="false"
        highlight-current
        :current-node-key="defaultCheck"
        :props="{ label: 'name', value: '_id' }"
        :filter-method="filterMethod"
        :item-size="48"
        :data="data"
        ref="treeRef"
        :height="580"
      >
        <template #default="{ node }">
          <el-tooltip :show-after="500" placement="top" :content="node.label">
            <span class="label">{{ truncate(node.label, { length: 12 }) }}</span>
          </el-tooltip>
          <span v-show="node.data.len">（{{ node.data.len }}）</span>
          <i
            @click="(e) => optionClick(node, e)"
            v-show="!node.data.noMenu"
            data-is-menu="1"
            class="MC_iconfont MC_icon-gengduo-shu option-btn"
          >
          </i>
          <span v-show="node.data.createAccess" title="创建一级服务组" ref="addServiceRef">
            <!-- <el-tooltip effect="dark" content="创建一级服务组" placement="top-center"> -->
            <i @click="onJump" class="MC_iconfont MC_icon-tianjia-yuan-xian left-space"></i>
            <!-- </el-tooltip> -->
          </span>
        </template>
      </el-tree-v2>
      <tree-menu
        v-if="!isEmpty(node)"
        :key="node.key"
        :node="node"
        :getNodeIndex="getNodeIndex"
        :top="top"
        :left="left"
        :visible="menuVisible"
        @hide="onHideMenu"
        @item-click="onMenuClick"
      ></tree-menu>
    </div>
    <service-group v-if="edit" />
  </div>
</template>
<script lang="ts" setup>
/* eslint-disable no-undef */
import { onMounted, reactive, toRefs, ref, defineExpose, onBeforeMount, markRaw } from 'vue'
import localforage from 'localforage'
import {
  getAllServiceGroup,
  getUnServiceGroup,
  getServiceGroup,
  delServiceGroup,
  upDownServiceGroup
} from '@app/base/apis/staff'
import useTree from '@/common/utils/hooks/use-tree'
import { Search } from '@element-plus/icons-vue'
import treeMenu from './tree-menu.vue'
import * as ids from '../constance'
import { ElMessage, ElMessageBox, ElTreeV2 } from 'element-plus'
import { cloneDeep, debounce, isEmpty, truncate } from 'lodash'
import { useRouter } from 'vue-router'
import ServiceGroup from '../service-group/service-group.vue'
import { addFields, deepToRaw } from '@/common/utils/tree'
import { TagNode } from '@/common/interface/node'
import { GROUP_STORE_PRE, ALL, UN_GROUP } from './constance'
import mcGetCache from '@/common/utils/mc-get-cache'
import deleteIcon from '@/common/components/delete-icon/index.vue'
if (!ElTreeV2.itemSizeLoad) {
  ElTreeV2.setup1 = ElTreeV2.setup
  ElTreeV2.setup = (props, ctx) => {
    const obj = ElTreeV2.setup1(props, ctx)
    obj['itemSize'] = ctx.attrs['item-size']
    ElTreeV2.itemSizeLoad = true
    return obj
  }
}

interface State {
  data: any
  top: number
  left: number
  menuVisible: boolean
  node: Partial<TagNode>
  edit: any
  defaultCheck: string
}

interface Props {
  hasAgent: boolean
}

const props = withDefaults(defineProps<Props>(), {
  hasAgent: false
})

const emits = defineEmits(['onNodeClick'])

const treeRef: any = ref(null)

const boxRef: any = ref(null)

const treeBox: any = ref(null)

const addServiceRef: any = ref(null)

const state: State = reactive({
  data: [],
  top: 0,
  left: 0,
  menuVisible: false,
  node: {},
  edit: null,
  defaultCheck: ''
})

const { data, top, left, menuVisible, node, edit, defaultCheck } = toRefs(state)

const setTree = (data: any) => {
  state.data = cloneDeep(data)
}

const hideMenu = debounce(() => {
  if (state.menuVisible) {
    state.menuVisible = false
  }
})

onMounted(() => {
  setTimeout(async () => {
    await mcGetCache.$getCache('groupCache', 'hasObj')
    treeBox.value = boxRef.value.querySelector('.el-tree-virtual-list')
    treeBox.value && treeBox.value.addEventListener('scroll', hideMenu)
  }, 1000)
})

onBeforeMount(() => {
  treeBox.value && treeBox.value.removeEventListener('scroll', hideMenu)
})

const router = useRouter()

const {
  filter: { onChange, filterMethod, query },
  moveUp,
  moveDown,
  getNodeIndex
} = useTree({
  treeRef,
  setTree,
  treeData: data,
  props: {
    value: '_id',
    label: 'name'
  }
})

const onNodeClick = (data: any) => {
  state.defaultCheck = data._id || ''
  emits('onNodeClick', data)
}

const optionClick = (nodeBox: any, e: MouseEvent) => {
  const { data: node } = nodeBox || {}
  state.menuVisible = true
  state.node = node
  const { left, top } = (e?.target as any)?.getBoundingClientRect()
  state.top = top
  state.left = left
}

const onHideMenu = () => {
  state.menuVisible = false
}

const menuAddSibling = () => {
  onJump()
}

const onJump = async (id?: any, isChild?: boolean) => {
  const store = cloneDeep(deepToRaw([state.node]))
  const parentId = isChild ? state.node._id : state.node.parentId
  let level = isChild ? +store[0].level + 1 : +store[0].level
  level = Number.isNaN(level) ? 0 : level
  if (typeof id !== 'string') {
    return router.push(`/staff/department/service_group?level=${level}&parentId=${parentId}`)
  }
  localforage.setItem(`${GROUP_STORE_PRE}${id}`, store[0])
  router.push(`/staff/department/service_group?id=${id}&level=${level}&parentId=${parentId}`)
}

const menuAddChild = () => {
  if (props.hasAgent) {
    return ElMessageBox.confirm('需移除当前服务组下全部人员后，才可新建子级服务组', {
      title: '提示',
      type: 'warning',
      confirmButtonText: '知道了',
      showCancelButton: false
    })
  }
  onJump(null, true)
}

const menuEdit = () => {
  onJump(state.node._id)
}

const onMove = async (target: any) => {
  await upDownServiceGroup({
    _id: state.node._id,
    targetId: target._id
  })
}

const menuUp = async () => {
  const target: any = moveUp(state.node)
  await onMove(target)
  ElMessage.success('上移成功')
  onHideMenu()
}

const menuDown = async () => {
  const target: any = moveDown(state.node)
  await onMove(target)
  ElMessage.success('下移成功')
  onHideMenu()
}

const menuDel = async () => {
  if (state.node?.children?.length) {
    await ElMessageBox.confirm('需要删除当前服务组的所有子服务组后才可删除', {
      title: '删除',
      type: 'error',
      showCancelButton: false,
      confirmButtonText: '知道了'
    })
    return
  }
  ElMessageBox.confirm('删除服务组后将不可找回，组内成员可在所有人中查询，请谨慎操作', {
    title: '删除',
    type: 'error',
    icon: markRaw(deleteIcon)
  }).then(async () => {
    const _id: any = state.node._id
    await delServiceGroup({
      _id
    })
    if (_id === defaultCheck.value) {
      return init()
    }
    getData()
  })
}

const menuActionMap: Record<string, () => void> = {
  [ids.ADD_SIBLING]: menuAddSibling,
  [ids.ADD_CHILD]: menuAddChild,
  [ids.EDIT]: menuEdit,
  [ids.MOVE_UP]: menuUp,
  [ids.MOVE_DOWN]: menuDown,
  [ids.DEL]: menuDel
}

const onMenuClick = (i: any) => {
  menuActionMap[i.id]?.()
}

const init = async () => {
  await getData()
  state.defaultCheck = state.data[0]._id
  setTimeout(() => emits('onNodeClick', state.data[0]))
}

onMounted(async () => {
  await init()
})

const getData = async () => {
  const allRes = await getAllServiceGroup({
    page: 1,
    pageSize: 10
  })
  const unRes = await getUnServiceGroup({
    page: 1,
    pageSize: 10
  })
  const res = await getServiceGroup()
  const data: any = [null, ...res.data, null]
  const list = data.map((node: any, index: number) => {
    if (index === 0) {
      return {
        _id: ALL,
        name: '所有人',
        len: allRes.data.count,
        noMenu: true,
        createAccess: true
      }
    }
    if (index === data.length - 1) {
      return {
        _id: UN_GROUP,
        name: '未分组',
        noMenu: true,
        len: unRes.data.count
      }
    }
    return node
  })
  addFields(list)
  state.data = list
}
defineExpose({
  getData
})
</script>
<style lang="stylus" scoped>
.left-space
  margin-left 70px

.flex
  display flex
  justify-content space-between
  align-items center
.box
  padding: 0 20px 0 10px;
  border-right: 1px solid rgba(0, 0, 0, 0.1);
.title
  width: 200px;
  height: 56px;
  line-height: 56px;
  letter-spacing: 0.001em;
  color: rgba(0,0,0,0.88);
  font-weight: 400;
  font-size: 16px;
  padding-left: 10px;
  box-sizing: border-box;
.tree-search
  margin 16px 0
  :deep(.el-input__wrapper)
    height 36px
    border-radius 18px
    box-shadow: unset;
    background: var(--mc-gray2-color);
    margin-left: 10px;
.option-btn
  display none
  color: rgba(0, 0, 0, 0.6);
  width: 24px;
  height: 24px;
  line-height: 24px;
  text-align: center;
  box-sizing: border-box;
  background: var(--mc-gray4-color);
  border-radius: 4px;
  position: absolute;
  right: 10px;
.label:hover .option-btn
  display block
.tree
  :deep() {
    .el-tree-node {
      color: rgba(0, 0, 0, 0.88);
    }
    .el-tree-node__expand-icon {
      margin-right: 4px;
    }
  }
  :deep(.el-tree-node__content)
    height 40px
    position: relative;
    border-radius: 4px;
  :deep
    .el-tree-node__content:hover > .option-btn
      display block
</style>
